package com.ruoyi.web.controller.tool;

import cn.hutool.core.util.IdUtil;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.baidu.BaiduTtsTokenHolder;
import com.ruoyi.common.utils.baidu.ConnUtil;
import com.ruoyi.common.utils.file.FileUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

@Slf4j
@RestController
@RequestMapping("/tool/baidutts")
public class BaiduTtsController extends BaseController {

    @Autowired
    private BaiduTtsTokenHolder baiduTtsTokenHolder;

    //临时token
    private String tempToken = "25.79b850086071ba7ed3878a9cd95da1c0.315360000.2013470715.282335-41603746";

    // text 的内容为"欢迎使用百度语音合成"的urlencode,utf-8 编码
    // 可以百度搜索"urlencode"
    private final String text = "A01电量低，请及时充电";

    // 发音人选择, 基础音库：0为度小美，1为度小宇，3为度逍遥，4为度丫丫，
    // 精品音库：5为度小娇，103为度米朵，106为度博文，110为度小童，111为度小萌，默认为度小美
    private final int per = 0;
    // 语速，取值0-15，默认为5中语速
    private final int spd = 10;
    // 音调，取值0-15，默认为5中语调
    private final int pit = 5;
    // 音量，取值0-9，默认为5中音量
    private final int vol = 5;

    // 下载的文件格式, 3：mp3(default) 4： pcm-16k 5： pcm-8k 6. wav
    private final int aue = 3;

    public final String url = "http://tsn.baidu.com/text2audio"; // 可以使用https

    private String cuid = "1234567JAVA";

    @Data
    public static class Text2AudioConfig {
        /**
         * 合成的文本，必填。文本长度必须小于1024GBK字节。建议每次请求文本不超过120字节，约为60个汉字或者字母数字。
         * 请注意计费统计依据：120个GBK字节以内（含120个）记为1次计费调用；每超过120个GBK字节则多记1次计费调用。
         * 如需合成更长文本，推荐使用长文本在线合成。
         */
        String tex;
        String tok;
        /**
         * 用户唯一标识，必填，用来计算UV值。建议填写能区分用户的机器 MAC 地址或 IMEI 码，长度为60字符以内。
         */
        String cuid;
        /**
         * 客户端类型选择，必填，web端填写固定值1。
         */
        String ctp;
        /**
         * 固定值zh。语言选择,必填，目前只有中英文混合模式，填写固定值zh。
         */
        String lan;
        /**
         * 语速，选填，取值0-15，默认为5中语速。
         */
        Integer spd;
        /**
         * 音调，选填，取值0-15，默认为5中语调
         */
        Integer pit;
        /**
         * 音量，选填，基础音库取值0-9，精品音库取值0-15，默认为5中音量（取值为0时为音量最小值，并非为无声）
         */
        Integer vol;
        /**
         * 发音人选择, 选填。默认为度小美(0)
         * 基础音库：0为度小美，1为度小宇，3为度逍遥，4为度丫丫，
         * 精品音库：5为度小娇，103为度米朵，106为度博文，110为度小童，111为度小萌，
         */
        Integer per;
        /**
         * 3为mp3格式(默认)； 4为pcm-16k；5为pcm-8k；6为wav（内容同pcm-16k）; 注意aue=4或者6是语音识别要求的格式，但是音频内容不是语音识别要求的自然人发音，所以识别效果会受影响。
         */
        Integer aue;
    }

    @PostMapping("/text2audio")
    public AjaxResult text2audio(@RequestBody Text2AudioConfig text2AudioConfig, HttpServletResponse response, HttpServletRequest request) {
        String token = baiduTtsTokenHolder.getToken();
        text2AudioConfig.setTok(token);

        if (Objects.isNull(text2AudioConfig.getCtp())) {
            text2AudioConfig.setCtp("1");
        }

        if (Objects.isNull(text2AudioConfig.getLan())) {
            text2AudioConfig.setLan("zh");
        }

        if (Objects.isNull(text2AudioConfig.getSpd())) {
            text2AudioConfig.setSpd(5);
        }

        if (Objects.isNull(text2AudioConfig.getPit())) {
            text2AudioConfig.setPit(5);
        }

        if (Objects.isNull(text2AudioConfig.getVol())) {
            text2AudioConfig.setVol(5);
        }

        if (Objects.isNull(text2AudioConfig.getAue())) {
            text2AudioConfig.setAue(3);
        }

        if (Objects.isNull(text2AudioConfig.getPer())) {
            text2AudioConfig.setPer(0);
        }

        try {
            String audioFilePath = getBaiduTtsAudioFilePath(text2AudioConfig);

            if (StringUtils.isEmpty(audioFilePath)) {
                throw new ServiceException("获取百度智能云tts语音合成文件路径失败.");
            }

//            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
//            response.setContentType(MediaType.MULTIPART_FORM_DATA_VALUE);
//            FileUtils.setAttachmentResponseHeader(response, "result3.mp3");
//
//            FileUtils.writeBytes(audioFilePath, response.getOutputStream());


            byte[] bytes = Files.readAllBytes(Paths.get(audioFilePath));
            // 使用 Base64 编码器将字节数组转换为 Base64 字符串
            String base64String = Base64.getEncoder().encodeToString(bytes);

            AjaxResult ajaxResult = AjaxResult.success();
            ajaxResult.put("audio", String.format("data:audio/wav;base64,%s", base64String));
            new Timer().schedule(new TimerTask() {
                @Override
                public void run() {
                    FileUtils.deleteFile(audioFilePath);
                }
            }, 5000);

            return ajaxResult;
        } catch (IOException e) {
//            throw new RuntimeException(e);
            throw new ServiceException("获取百度智能云tts语音合成文件路径失败.");
        }
    }

    /**
     * 获取百度智能云tts语音合成文件路径。
     *
     * @param text2AudioConfig
     * @return
     * @throws IOException
     */
    private String getBaiduTtsAudioFilePath(Text2AudioConfig text2AudioConfig) throws IOException {
        log.info("text2AudioConfig: {}", text2AudioConfig);

        String filePath = null;
        // 此处2次urlencode， 确保特殊字符被正确编码
        String params = "tex=" + ConnUtil.urlEncode(ConnUtil.urlEncode(text2AudioConfig.getTex()));
        params += "&per=" + text2AudioConfig.getPer();
        params += "&spd=" + text2AudioConfig.getSpd();
        params += "&pit=" + text2AudioConfig.getPit();
        params += "&vol=" + text2AudioConfig.getVol();
        params += "&cuid=" + cuid;
        params += "&tok=" + text2AudioConfig.getTok();
        params += "&aue=" + text2AudioConfig.getAue();
        params += "&lan=zh&ctp=1";
        System.out.println(url + "?" + params); // 反馈请带上此url，浏览器上可以测试
        HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setConnectTimeout(5000);
        PrintWriter printWriter = new PrintWriter(conn.getOutputStream());
        printWriter.write(params);
        printWriter.close();

        Map<String, List<String>> headers = conn.getHeaderFields();
//        Map<String, List<String>> headers = httpResponse.headers();
        for (String key : headers.keySet()) {
            log.info("key: {}----value: {}", key, headers.get(key));
        }

        String contentType = conn.getContentType();
        if (contentType.contains("audio/")) {
            byte[] bytes = ConnUtil.getResponseBytes(conn);
            String format = getFormat(aue);
            File file = new File("tts_audio_" + IdUtil.fastUUID() + "." + format); // 打开mp3文件即可播放
            // System.out.println( file.getAbsolutePath());
            FileOutputStream os = new FileOutputStream(file);
            os.write(bytes);
            os.close();

            filePath = file.getAbsolutePath();
            System.out.println("audio file write to " + filePath);
        } else {
            System.err.println("ERROR: content-type= " + contentType);
            String res = ConnUtil.getResponseString(conn);
            System.err.println(res);
        }

        return filePath;
    }

    // 下载的文件格式, 3：mp3(default) 4： pcm-16k 5： pcm-8k 6. wav
    private String getFormat(int aue) {
        String[] formats = {"mp3", "pcm", "pcm", "wav"};
        return formats[aue - 3];
    }

}
